
#include "pwm_msp_init.h"

TIM_HandleTypeDef Tim4Handle;
__IO uint16_t TIM4_cnt = 0;

void pwm_gpio_init()
{
    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStruct = {0};

    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void pwm_timer_init()
{
    /* Peripheral clock enable */
    __HAL_RCC_TIM4_CLK_ENABLE();

    TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    TIM_MasterConfigTypeDef sMasterConfig = {0};
    TIM_OC_InitTypeDef sConfigOC = {0};

    Tim4Handle.Instance = TIM4;
    Tim4Handle.Init.Prescaler = 30/*720*/ - 1;
    Tim4Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    Tim4Handle.Init.Period = 0xFFFF;
    Tim4Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    Tim4Handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

    if (HAL_TIM_Base_Init(&Tim4Handle) != HAL_OK)
    {
        Error_Handler();
    }

    sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
    sConfigOC.Pulse = 0;
    sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
    sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

    if (HAL_TIM_OC_ConfigChannel(&Tim4Handle, &sConfigOC, TIM_CHANNEL_4) != HAL_OK)
    {
        Error_Handler();
    }

    /* TIM4 interrupt Init */
    HAL_NVIC_SetPriority(TIM4_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM4_IRQn);

    HAL_TIM_OC_Start_IT(&Tim4Handle, TIM_CHANNEL_4);
}

void pwm_msp_init()
{
    pwm_gpio_init();
    pwm_timer_init();
}

void TIM4_IRQHandler()
{
    if (__HAL_TIM_GET_FLAG(&Tim4Handle, TIM_IT_CC4) != RESET) {
        // 因为捕获比较寄存器的值是 16 位的设置的值不能超过 65535 如果超过那么会自动减 65535(溢出)
        __IO uint16_t count = 0;

        // 获取捕获比较寄存器的值
        count = __HAL_TIM_GetCounter(&Tim4Handle);

        // 重新设置捕获比较寄存器的值, %0xFFFF 防止溢出
        __HAL_TIM_SET_COMPARE(&Tim4Handle, TIM_CHANNEL_4, (count + TIM4_cnt) % 0xFFFF);

        __HAL_TIM_CLEAR_IT(&Tim4Handle, TIM_IT_CC4);
    }
}

static void Error_Handler()
{
    while (1)
    {

    }
}

/*******************************************
 *          PWM MSP TEST
 ******************************************/

void pwm_test_gpio_init()
{
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}

void pwm_test_gpio()
{
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET);
    HAL_Delay(20);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET);
    HAL_Delay(20);
}
